package mn.more.wits.server.dao.temp;

import java.text.DateFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import mn.more.mock.io.MockModel;
import mn.more.wits.client.dto.ExamListDTO;
import mn.more.wits.client.dto.ExamSummaryDTO;
import mn.more.wits.server.dao.ExamListingDAO;
import mn.more.wits.server.model.ExamTaker;
import org.apache.commons.lang.StringUtils;
import org.apache.log4j.Logger;

/**
 * @author $Author: mikeliucc $
 * @version $Id: TestExamListingDAO.java 5 2008-09-01 12:08:42Z mikeliucc $
 */
public class TestExamListingDAO extends AbstractTestDataDAO implements ExamListingDAO {

	private static final DateFormat DF = new SimpleDateFormat("yyyy.MM.dd hh:mm");

	private transient Logger logger = Logger.getLogger(TestExamListingDAO.class);

	protected Logger getLogger() { return logger; }

	public ExamListDTO listAvailableExams(ExamTaker account) {
		if (debug) { refreshData(); }

		String username = account.getLoginId();
		List<ExamSummaryDTO> list = new ArrayList<ExamSummaryDTO>();
		MockModel userExams = rootModel.getRefModel(username);
		String[] examIds = userExams.getStringArray("testIds");
		for (String examId : examIds) {
			MockModel exam = rootModel.getRefModel(examId);
			ExamSummaryDTO summary = toExamSummary(examId, exam);
			if (summary == null) { continue; }
			list.add(summary);
		}

		ExamSummaryDTO[] summaries = new ExamSummaryDTO[list.size()];
		for (int i = 0; i < summaries.length; i++) { summaries[i] = list.get(i); }
		ExamListDTO examList = new ExamListDTO();
		examList.setSummaries(summaries);
		return examList;
	}

	private ExamSummaryDTO toExamSummary(String examId, MockModel exam) {
		// check required fields
		if (exam == null) {
			logger.error("BAD DATA!!! Model not found based on id '" + examId + "'");
			return null;
		}

		String testName = exam.getString("testName");
		if (StringUtils.isEmpty(testName)) {
			logger.error("BAD DATA!!! exam " + examId + "'s 'testName' not found on exam '" + examId + "'");
			return null;
		}

		String subjectName = exam.getString("subjectName");
		if (StringUtils.isEmpty(subjectName)) {
			logger.error("BAD DATA!!! exam " + examId + "'s 'subjectName' not found on exam '" + examId + "'");
			return null;
		}

		int maxExamTime = 0;
		try {
			maxExamTime = exam.getInt("maxMinutes");
			if (maxExamTime < 1) {
				logger.error("BAD DATA!!! exam " + examId + "'s 'maxMinutes' less than 1 minutes");
				return null;
			}
		} catch (Throwable e) {
			logger.error("BAD DATA!!! exam " + examId + "'s 'maxMinutes' was not defined", e);
		}

		int totalQuestions = 0;
		try {
			totalQuestions = exam.getInt("totalQuestions");
			if (totalQuestions < 1) {
				logger.error("BAD DATA!!! exam " + examId + "'s 'totalQuestions' is less than 1");
				return null;
			}
		} catch (Exception e) {
			logger.error("BAD DATA!!! exam " + examId + "'s 'totalQuestions' was not defined", e);
		}

		String endDateString = exam.getString("availableUntil");
		if (StringUtils.isEmpty(endDateString)) {
			logger.error("BAD DATA!!! exam " + examId + "'s 'availableUntil' not found on exam '" + examId + "'");
			return null;
		}

		String startDateString = exam.getString("availableSince");
		if (StringUtils.isEmpty(startDateString)) {
			logger.error("BAD DATA!!! exam " + examId + "'s 'availableSince' not found on exam '" + examId + "'");
			return null;
		}

		long currentTs = System.currentTimeMillis();

		Date availableUntil = null;
		try {
			availableUntil = DF.parse(endDateString);
			if (availableUntil.getTime() <= currentTs) {
				if (logger.isDebugEnabled()) {
					logger.debug("Exam '" + examId + "' has already expired... skipping...");
				}
				return null;
			}
		} catch (ParseException e) {
			logger.error("BAD DATA!!! exam " + examId + "'s 'availableUntil' was not of the correct " +
			             "format ('yyyy.MM.dd hh:mm')!", e);
		}

		Date availableSince = null;
		try {
			availableSince = DF.parse(startDateString);
			if ((availableUntil.getTime() - availableSince.getTime()) < maxExamTime) {
				logger.error("BAD DATA!!! not enough time alloated to fit 'maxMinutes' for exam '" + exam + "'");
				return null;
			}
		} catch (ParseException e) {
			logger.error("BAD DATA!!! exam " + examId + "'s 'availableSince' was not of the correct " +
			             "format ('yyyy.MM.dd hh:mm')!", e);
		}

		ExamSummaryDTO summary = new ExamSummaryDTO();
		summary.setTestId(examId);
		summary.setTestName(testName);
		summary.setSubjectName(subjectName);
		summary.setAvailableSince(availableSince);
		summary.setAvailableUntil(availableUntil);
		summary.setMaxMinutes(maxExamTime);
		summary.setTotalQuestions(totalQuestions);
		summary.setComments(exam.getString("comments"));
		summary.setRequiredTools(exam.getString("requiredTools"));
		summary.setTeamwork(exam.getBoolean("teamwork"));

		return summary;
	}
}
